import time
from typing import Union

from fastapi import APIRouter, Depends, Body
from peewee_async import Manager

from common.config.settings import Settings
from common.g.g import G_REDIS
from common.pkg.jwt_util import generate_jwt_token
from common.route.tenant_route import ClientTenantBaseAPIRoute
from common.route.user_route import ClientMustLoginAPIRoute
from common.route.route import ZipCustomerRoute
from common.utils.depends.client_depends import get_cli_tenant, get_cli_user, get_cli_user_id, get_cli_tenant_id
from common.utils.depends.common import get_mgw, get_request_id, get_settings
from common.utils.lock.lock_dec import lock
from common.utils.resp import JsonResponse
from common.v.v import DATAORCODE
from common.pkg.fastapi_util import cbv
from core.view import ClientBaseView
from schema.req_schema.client_user_req_schema import AddNewClientUserRequestModel, ClientUserLoginRequestModel
from service.client_user_service import ClientUserService, ClientUserPointService

router = APIRouter(prefix="/user", tags=["client_user"], route_class=ClientTenantBaseAPIRoute)

login_router = APIRouter(prefix="/user", tags=["client_user"], route_class=ZipCustomerRoute(ClientTenantBaseAPIRoute, ClientMustLoginAPIRoute))


@cbv(router)
class AnyUserView(ClientBaseView):

    @router.post("/register", description="用户注册")
    async def register_new_user(self,
                                req_model: AddNewClientUserRequestModel = Body(),
                                ):
        req_model.tenant_id = self.tenant_id
        lock_key = f"email:{req_model.email}:phone:{req_model.phone}"
        lock_value = self.request_id
        lock_time = 30
        execute_time = 2000
        cus = ClientUserService(self.mgw, self.redis)
        res = await lock(lock_key, lock_value, lock_time, execute_time)(cus.register)(req_model)
        if res is None:
            return JsonResponse().inner_error(msg="服务异常")
        else:
            ok, data_or_code = res
            return self.unpack_response(ok, data_or_code)

    @router.post("/login", description="用户登陆")
    async def login(self,
                    req_model: ClientUserLoginRequestModel = Body(...),
                    settings: Settings = Depends(get_settings)
                    ):
        cus = ClientUserService(self.mgw, self.redis)
        ok, data_or_code = await cus.query_user_by_email_and_password(self.tenant_id, req_model)
        if ok:
            user_data = data_or_code.data
            payload = {"user_id": user_data["user_id"], "username": user_data["username"], "exp": time.time() + settings.jwt_config.timeout}
            token = generate_jwt_token(payload, settings.jwt_config.client_secret, settings.jwt_config.algorithms)
            return JsonResponse(data={"token": token}).to_response()
        else:
            return JsonResponse(code=data_or_code.code, msg=data_or_code.msg).to_response()


class LoginUserView(ClientBaseView):

    @login_router.get("/current", description="获取当前登陆用户的信息")
    async def get_current_user(self, current_user: Union[dict, DATAORCODE] = Depends(get_cli_user)):
        if isinstance(current_user, DATAORCODE):
            return JsonResponse(code=current_user.code, msg=current_user.msg).to_response()
        else:
            return JsonResponse(data=current_user).to_response()

    @login_router.get("/current/point", description="获取当前登陆用户的积分信息")
    async def get_current_user_point(self):
        cup = ClientUserPointService(self.mgw, self.redis)
        ok, data_or_code = await cup.get_user_point(self.tenant_id, self.user_id)
        return self.unpack_response(ok, data_or_code)


